/******************************************************************************/
/* File: flowConfig.cpp                                                       */
/******************************************************************************/

#include "flowConfig.h"

/******************************************************************************/
/*
稳恒流量模型 ==== 速率保持不变
   ----------------------------------------------------------------------------

|||------------------------------------------------------------------------->>>
 */
/******************************************************************************/
int64_t StableFlowModel::GetNextRate() {
    return iRate;
}
    
cJSON* StableFlowModel::GenToJson() {
    cJSON *j = cJSON_CreateObject();
    if( j == NULL )
        std::cout << "Memory Error: Cannot create JSON object." << std::endl;
    else
        cJSON_AddIntToObject(j, "Rate", iRate);
        
    return j;
}

void StableFlowModel::ParseFromJson(cJSON *json) {
    cJSON *pj;
    
    if ((pj = cJSON_GetObjectItem(json, "Rate")) != NULL)
        iRate = pj->valueint;
}

/******************************************************************************/
/*
方波流量模型 ==== 速率在两个速率间来回跳动
如：
        -----------                   -------------------      -------   maxRate
        |         |                   |                  |     |     |
---------         ---------------------                  -------     --- minRate 

|||--------------------------------------------------------------------------->>>
 */
/******************************************************************************/

int64_t RectFlowModel::GetNextRate() {
    int limit = (int)(fMaxProportion * 1000);

    srand((int)time(0));
    int rd = rand()%1000;

    if(rd > limit)
        return iMinRate;

    return iMaxRate;
}
    
cJSON* RectFlowModel::GenToJson() {
    cJSON *j = cJSON_CreateObject();

    if( j == NULL )
        std::cout << "Memory Error: Cannot create JSON object." << std::endl;
    else{
        cJSON_AddIntToObject(j, "MaxRate", iMaxRate);
        cJSON_AddIntToObject(j, "MinRate", iMinRate);
        cJSON_AddFloatToObject(j, "Proportion", fMaxProportion);
    }

    return j;
}

void RectFlowModel::ParseFromJson(cJSON *json) {
    cJSON *pj;
    
    if ((pj = cJSON_GetObjectItem(json, "MaxRate")) != NULL)
        iMaxRate = pj->valueint;
        
    if ((pj = cJSON_GetObjectItem(json, "MinRate")) != NULL)
        iMinRate = pj->valueint;
        
    if ((pj = cJSON_GetObjectItem(json, "Proportion")) != NULL)
        fMaxProportion = pj->valuefloat;
}

/******************************************************************************/
/*
泊松流量模型 ==== 完全随机的流量过程
 */
/******************************************************************************/

int64_t PoissonFlowModel::GetNextRate() {
    srand((int)time(0));
    int rd = rand()%1000;
        
    double p = (double)rd / 1000;
    int64_t newRate = (int) (p * iBurstRate);
        
    return newRate;
}
    
cJSON* PoissonFlowModel::GenToJson() {
    cJSON *j = cJSON_CreateObject();
    if( j == NULL )
        std::cout << "Memory Error: Cannot create JSON object." << std::endl;
    else{
        cJSON_AddIntToObject(j, "BurstMaxRate", iBurstRate);
    }
        
    return j;
}

void PoissonFlowModel::ParseFromJson(cJSON *json) {
    cJSON *pj;
    
    if ((pj = cJSON_GetObjectItem(json, "BurstMaxRate")) != NULL)
        iBurstRate = pj->valueint;
}

/******************************************************************************/
/*
自定义流量模型 ==== 暂时不做这部分工作
 */
/******************************************************************************/

/******************************************************************************/
/*
FlowConfig Class内容主要分为两部分：
1 连接信息
2 流量行为
 */
/******************************************************************************/
FlowConfig::FlowConfig() : 
            sSenderIP(NULL), sRecverIP(NULL), 
            iRole(1), iProto(1),
            iTime(-1), iTrafficModel(1), 
            pSfm(NULL), pRfm(NULL), pPfm(NULL){

}

FlowConfig::~FlowConfig() {
    
    if(sSenderIP){
        delete sSenderIP;
        sSenderIP = NULL;
    }
        
    if(sRecverIP) {
        delete sRecverIP;
        sRecverIP = NULL;
    }
    
    if(pSfm) {
        delete pSfm;
        pSfm = NULL;
    }
    
    if(pRfm) {
        delete pRfm;
        pRfm = NULL;
    }
    
    if(pPfm) {
        delete pPfm;
        pPfm = NULL;
    }
}

int64_t FlowConfig::GetNextRate() {
    switch(iTrafficModel) {
        case 1:
            return pSfm->GetNextRate();
        case 2:
            return pRfm->GetNextRate();
        case 3:
            return pPfm->GetNextRate();
    }
    
    return 0;
}

// 打印配置信息
void FlowConfig::PrintInfo() {
    std::cout << "\nFlowConfig Information: " << std::endl;
    std::cout << "Client Address: " << sSenderIP << std::endl;
    std::cout << "Client Port: " << iSenderPort << std::endl;
    std::cout << "Server Address: " << sRecverIP << std::endl;
    std::cout << "Server Port: " << iRecverPort << std::endl;
    std::cout << "Use IPv6: " << bUseIPv6 << std::endl;
    std::cout << "Role: " << ((iRole == 1) ? "Client" : "Server") << std::endl;
    std::cout << "Protocol: " << ((iProto == 1) ? "TCP" : "UDP") << std::endl;
    std::cout << "Traffic Model: " << ((iTrafficModel == 1) ? "StableFlowModel" : ((iTrafficModel == 2) ? "RectFlowModel" : "PoissonFlowModel") ) << std::endl;
    
    switch(iTrafficModel) {
        case 1:
            std::cout << "Stable Flow Model Info: " << std::endl;
            std::cout << "Rate: " << pSfm->iRate << std::endl;
            break;
        case 2:
            std::cout << "Rect Flow Model Info: " << std::endl;
            std::cout << "Max Rate: " << pRfm->iMaxRate << std::endl;
            std::cout << "Min Rate: " << pRfm->iMinRate << std::endl;
            std::cout << "MaxRate Proportion: " << pRfm->fMaxProportion << std::endl;
            break;
        case 3:
            std::cout << "Poisson Flow Model Info: " << std::endl;
            std::cout << "Burst Rate: " << pPfm->iBurstRate << std::endl;
            break;
    }
}
    
cJSON* FlowConfig::GenToJson() {
    
    cJSON *j = cJSON_CreateObject();
    if( j == NULL )
        std::cout << "Memory Error: Cannot create JSON object." << std::endl;
    else {
        cJSON_AddStringToObject(j, "SenderIP", sSenderIP);
        cJSON_AddIntToObject(j, "SenderPort", iSenderPort);
        cJSON_AddStringToObject(j, "RecverIP", sRecverIP);
        cJSON_AddIntToObject(j, "RecverPort", iRecverPort);
            
        cJSON_AddIntToObject(j, "UseIPv6", bUseIPv6);
        cJSON_AddIntToObject(j, "Role", iRole);
        cJSON_AddIntToObject(j, "Protocol", iProto);
        cJSON_AddIntToObject(j, "Time", iTime);
        
        cJSON_AddIntToObject(j, "TrafficModel", iTrafficModel);
        
        cJSON *json;
        switch(iTrafficModel) {
            case (1):
                json = pSfm->GenToJson();
                cJSON_AddItemToObject(j, "StableFlowModel", json);
                break;
            case (2):
                json = pRfm->GenToJson();
                cJSON_AddItemToObject(j, "RectFlowModel", json);
                break;
            case (3):
                json = pPfm->GenToJson();
                cJSON_AddItemToObject(j, "PoissonFlowModel", json);
                break;
        }
    }
        
    return j;
}

void FlowConfig::ParseFromJson(cJSON *json) {
    cJSON *pj;
    
    if ((pj = cJSON_GetObjectItem(json, "SenderIP")) != NULL)
        sSenderIP = strdup(pj->valuestring);
    
    if ((pj = cJSON_GetObjectItem(json, "SenderPort")) != NULL)
        iSenderPort = pj->valueint;
    
    if ((pj = cJSON_GetObjectItem(json, "RecverIP")) != NULL)
        sRecverIP = strdup(pj->valuestring);
        
    if ((pj = cJSON_GetObjectItem(json, "RecverPort")) != NULL)
        iRecverPort = pj->valueint;
    
    if ((pj = cJSON_GetObjectItem(json, "UseIPv6")) != NULL)
        bUseIPv6 = pj->valueint;

    if ((pj = cJSON_GetObjectItem(json, "Role")) != NULL)
        iRole = pj->valueint;
    
    if ((pj = cJSON_GetObjectItem(json, "Protocol")) != NULL)
        iProto = pj->valueint;
        
    if ((pj = cJSON_GetObjectItem(json, "TrafficModel")) != NULL)
        iTrafficModel = pj->valueint;
     
    switch(iTrafficModel) {
        case (1):
            if ((pj = cJSON_GetObjectItem(json, "StableFlowModel")) != NULL) {
                pSfm = new StableFlowModel();
                pSfm->ParseFromJson(pj);
            }
            break;
        case (2):
            if ((pj = cJSON_GetObjectItem(json, "RectFlowModel")) != NULL) {
                pRfm = new RectFlowModel();
                pRfm->ParseFromJson(pj);
            }
            break;
        case (3):
            if ((pj = cJSON_GetObjectItem(json, "PoissonFlowModel")) != NULL) {
                pPfm = new PoissonFlowModel();
                pPfm->ParseFromJson(pj);
            }
            break;
    }
}

/******************************************************************************/
/* End File: flowConfig.cpp                                                   */
/******************************************************************************/